import {
  getUserInfo,
  refreshAccessToken,
  userAccountLogin,
  userPhoneLogin,
} from '@/api/access'
import { toTimestamp } from '@/utils/date'
import storage from '@/utils/storage'
import { defineStore } from 'pinia'
import { computed, readonly, ref } from 'vue'

// 常量定义
const TOKEN_STORAGE = 'user-token'
const USER_STORAGE = 'user-info'

export const useUserStore = defineStore('user', () => {
  // TOKEN
  const userToken = ref<UserToken>()
  // 用户信息
  const userInfo = ref<UserInfo>({
    uid: 0,
    username: '',
    nickname: '',
    avatar: '',
    phone: '',
    email: '',
    remark: '',
  })
  // 设备ID
  const deviceId = ref<string>(uni.getSystemInfoSync().deviceId)
  // 弹窗锁（防止多次弹出）
  const confirmLock = ref<boolean>(false)

  // ----- Getters -----

  const isLogin = computed(() => !!userInfo?.value.uid && !!userToken?.value)

  const realToken = computed(() => {
    if (userToken.value) {
      // 判断是否过期
      const now = new Date().getTime()
      const expired = Number.parseInt(userToken.value.expires.toString()) - now <= 0
      if (!expired) {
        return userToken.value.accessToken
      }
    }
    return ''
  })

  const readAvatar = computed(() =>
    userInfo.value.avatar ? userInfo.value.avatar : '/static/avatar.png',
  )

  // ----- Actions -----

  /**
   * 初始化数据
   */
  const initStore = async () => {
    const info = storage.get<UserInfo>(USER_STORAGE)
    const token = storage.get<UserToken>(TOKEN_STORAGE)
    // 同时存在才会被判定为已登录
    if (info && token) {
      userInfo.value = info
      userToken.value = token
    }
  }

  /**
   * 设置用户信息
   *
   * @param info 用户信息
   */
  const setUserInfo = (info: UserInfo) => {
    userInfo.value = info
    storage.set<UserInfo>(USER_STORAGE, info)
  }

  /**
   * 设置用户TOKEN
   *
   * @param token TOKEN
   */
  const setUserToken = (token: UserToken) => {
    // 转换为毫秒时间戳
    token.expires = toTimestamp(token.expires)
    userToken.value = token
    storage.set<UserToken>(TOKEN_STORAGE, token)
  }

  /**
   * 设置空头像
   */
  const useEmptyAvatar = () => {
    setUserInfo({
      ...userInfo.value,
      avatar: '',
    })
  }

  /**
   * 刷新TOKEN
   *
   * @returns UserToken
   */
  const refreshToken = async (refreshToken: string) => {
    const tokenRes = await refreshAccessToken({
      uid: userInfo.value.uid,
      deviceId: deviceId.value,
      refreshToken,
    })
    setUserToken(tokenRes.data)
    return tokenRes.data
  }

  /**
   * 刷新用户信息
   *
   * @param needLogin 开启后只会在已登录的情况下执行请求
   * @returns {Promise<boolean>} Returns true if the user information is refreshed successfully, otherwise false.
   */
  const refreshUserInfo = async (needLogin: boolean = true) => {
    if (!needLogin || isLogin.value) {
      const infoRes = await getUserInfo()
      setUserInfo(infoRes.data)
      return true
    }
    else {
      return false
    }
  }

  /**
   * 用户登录（账号）
   *
   * @param passport 账号
   * @param password 密码
   */
  const loginByAccount = async (passport: string, password: string) => {
    const loginRes = await userAccountLogin({
      passport,
      password,
      deviceId: deviceId.value,
    })
    // 注：这里需要首先将登录后获取的token存储，以方便后续获取用户信息
    // 也可以通过修改后端api，在登录后一并返回用户信息，减少一次请求
    setUserToken(loginRes.data)
    await refreshUserInfo(false)
  }

  /**
   * 用户登录（短信）
   *
   * @param phone 手机号
   * @param code 验证码
   */
  const loginByPhone = async (phone: string, code: string) => {
    const loginRes = await userPhoneLogin({
      phone,
      code,
      deviceId: deviceId.value,
    })
    // 注：这里需要首先将登录后获取的token存储，以方便后续获取用户信息
    // 也可以通过修改后端api，在登录后一并返回用户信息，减少一次请求
    setUserToken(loginRes.data)
    await refreshUserInfo(false)
  }

  /**
   * 清空用户信息（包括token）
   */
  const clearUserInfo = () => {
    userInfo.value = {
      uid: 0,
      username: '',
      nickname: '',
      avatar: '',
      phone: '',
      email: '',
      remark: '',
    }
    userToken.value = undefined
    storage.remove(USER_STORAGE)
    storage.remove(TOKEN_STORAGE)
  }

  /**
   * 强制退出提示
   *
   * @param content 消息
   */
  const forceLogoutModal = (content: string) => {
    if (!confirmLock.value) {
      uni.showModal({
        title: '系统消息',
        content,
        showCancel: false,
        success() {
          clearUserInfo()
          confirmLock.value = false
          uni.switchTab({
            url: '/pages/mine/index',
          })
        },
      })
      confirmLock.value = true
    }
  }

  return {
    /** getter: 用户完整信息 */
    readUserInfo: readonly(userInfo),
    /** getter: TOKEN */
    readUserToken: readonly(userToken),
    /** getter: 获取token字符串，自动判断是否过期 */
    realToken,
    /** getter: 是否已登录 */
    isLogin,
    /** getter: 实际头像信息 */
    readAvatar,
    /** action: 初始化数据 */
    initStore,
    /** action: 用户登录（账号） */
    loginByAccount,
    /** action: 用户登录（短信） */
    loginByPhone,
    /** action: 刷新用户信息（未登录不操作） */
    refreshUserInfo,
    /** action: 刷新TOKEN */
    refreshToken,
    /** action: 设置空头像 */
    useEmptyAvatar,
    /** action: 清空用户信息（包括token） */
    clearUserInfo,
    /** action: 强制退出提示 */
    forceLogoutModal,
  }
})
